package com.hucc.datasource.core;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;

/**
 * 数据源实现类
 */
public class HuccDataSource implements DataSource {
    /**
     * 驱动类
     */
    private String driverClassName;

    /**
     * 连接的数据库url
     */
    private String url;

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 最大的连接数
     */
    private Integer maxActive = 8;

    /**
     * 最大的空闲连接
     */
    private Integer maxIdle = 8;

    /**
     * 最小的空闲连接数
     */
    private Integer minIdle = 0;

    /**
     * 获得连接最大的等待时间 单位毫秒
     */
    private Long maxWait;

    /**
     * 获取连接时，是否测试连接的有效性
     */
    private Boolean testOnBorrow = false;

    /**
     * 归还连接时，是否验证连接的有效性
     */
    private Boolean testOnReturn = false;

    /**
     * 验证连接有效性sql
     */
    private String validationQuery;

    /**
     * 验证sql执行的超时时间
     */
    private Long validationQueryTimeout;

    /**
     * 空闲连接销毁任务执行的间隔时间
     */
    private Long timeBetweenEvictionRunsMillis;

    /**
     * 空闲连接销毁任务验证的个数
     */
    private Integer numTestsPerEvictionRun = 3;

    /**
     *  空闲连接销毁的阀值 单位毫秒
     */
    private Long minEvictableIdleTimeMillis = 30 * 60 * 1000L;

    /**
     * 空闲连接销毁是否验证连接有效性
     */
    private Boolean testWhileIdle;

    /**
     * 连接池初始化大小
     */
    private Integer initialSize;

    /**
     * 连接池
     */
    private HuccConnectionPool connectionPool;

    private synchronized HuccConnectionPool createConnectionPool() {
        HuccConnectionPool connectionPool = new HuccConnectionPool();
        connectionPool.setDriverClassName(driverClassName);
        connectionPool.setUrl(url);
        connectionPool.setUsername(username);
        connectionPool.setPassword(password);
        connectionPool.setMaxActive(maxActive);
        connectionPool.setMaxIdle(maxIdle);
        connectionPool.setMinIdle(minIdle);
        connectionPool.setMaxWait(maxWait);
        connectionPool.setTestOnBorrow(testOnBorrow);
        connectionPool.setTestOnReturn(testOnReturn);
        connectionPool.setValidationQuery(validationQuery);
        connectionPool.setValidationQueryTimeout(validationQueryTimeout);
        connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
        connectionPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        connectionPool.setTestWhileIdle(testWhileIdle);

        connectionPool.initConnection(initialSize);

        return connectionPool;
    }

    @Override
    public Connection getConnection() throws SQLException {
        if (connectionPool == null) {
            this.connectionPool = createConnectionPool();
        }

        return connectionPool.borrowConnection();
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getMaxActive() {
        return maxActive;
    }

    public void setMaxActive(Integer maxActive) {
        this.maxActive = maxActive;
    }

    public Integer getMaxIdle() {
        return maxIdle;
    }

    public void setMaxIdle(Integer maxIdle) {
        this.maxIdle = maxIdle;
    }

    public Integer getMinIdle() {
        return minIdle;
    }

    public void setMinIdle(Integer minIdle) {
        this.minIdle = minIdle;
    }

    public Long getMaxWait() {
        return maxWait;
    }

    public void setMaxWait(Long maxWait) {
        this.maxWait = maxWait;
    }

    public Boolean getTestOnBorrow() {
        return testOnBorrow;
    }

    public void setTestOnBorrow(Boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public Boolean getTestOnReturn() {
        return testOnReturn;
    }

    public void setTestOnReturn(Boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }

    public String getValidationQuery() {
        return validationQuery;
    }

    public void setValidationQuery(String validationQuery) {
        this.validationQuery = validationQuery;
    }

    public Long getValidationQueryTimeout() {
        return validationQueryTimeout;
    }

    public void setValidationQueryTimeout(Long validationQueryTimeout) {
        this.validationQueryTimeout = validationQueryTimeout;
    }

    public Long getTimeBetweenEvictionRunsMillis() {
        return timeBetweenEvictionRunsMillis;
    }

    public void setTimeBetweenEvictionRunsMillis(Long timeBetweenEvictionRunsMillis) {
        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
    }

    public Integer getNumTestsPerEvictionRun() {
        return numTestsPerEvictionRun;
    }

    public void setNumTestsPerEvictionRun(Integer numTestsPerEvictionRun) {
        this.numTestsPerEvictionRun = numTestsPerEvictionRun;
    }

    public Long getMinEvictableIdleTimeMillis() {
        return minEvictableIdleTimeMillis;
    }

    public void setMinEvictableIdleTimeMillis(Long minEvictableIdleTimeMillis) {
        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
    }

    public Boolean getTestWhileIdle() {
        return testWhileIdle;
    }

    public void setTestWhileIdle(Boolean testWhileIdle) {
        this.testWhileIdle = testWhileIdle;
    }

    public Integer getInitialSize() {
        return initialSize;
    }

    public void setInitialSize(Integer initialSize) {
        this.initialSize = initialSize;
    }
}
